package com.ruiysoft;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.*;

/**
 * Created by 化增光 on 2017/5/12.
 */
public class WeChatUtil {

    //配置微信公众号时填写的Token
    private static final String token = "cnguanai888";
    public static boolean checkSignature(String signature, String timestamp, String nonce) {

        // 拼接字符串
        String[] arr = new String[] { token, timestamp, nonce };
        // 排序
        Arrays.sort(arr);
        // 生成字符串
        StringBuffer content = new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        // SHA1加密
//        String tmp = DecriptUtil.SHA1(content.toString());
//        return tmp.equals(signature);
        return false;
    }

    /**
     * 生成签名sign
     * 第一步：非空参数值的参数按照参数名ASCII码从小到大排序，按照键值对的形式。生成字符串StringA
     * stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
     * 第二部：拼接API密钥，这里的秘钥是微信商户平台的秘钥，是自己设置的，不是公众号的秘钥
     * stringSignTemp="stringA&key=192006250b4c09247ec02edce69f6a2d"
     * 第三部：MD5加密
     * sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7"
     *
     * @param map 不包含空字符串的map
     * @return
     */
    public static String sign(Map<String, String> map, String key) {
        //排序
        String sort=sortParameters(map);
        //拼接API秘钥
        sort=sort+"&key="+key;
        //System.out.println(sort);
        //MD5加密
        String sign=md5(sort).toUpperCase();
        return sign;
    }

    private static String md5(String in) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(in.getBytes("UTF-8"));
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);

        } catch (Exception e) {
            ;
        }

        return "error";
    }

    /**
     * 对参数列表进行排序，并拼接key=value&key=value形式
     * @param map
     * @return
     */
    private static String sortParameters(Map<String, String> map) {
        Set<String> keys = map.keySet();
        List<String> paramsBuf = new ArrayList<String>();
        for (String k : keys) {
            paramsBuf.add((k + "=" + getParamString(map, k)));
        }
        // 对参数排序
        Collections.sort(paramsBuf);
        String result="";
        int count=paramsBuf.size();
        for(int i=0;i<count;i++){
            if(i<(count-1)){
                result+=paramsBuf.get(i)+"&";
            }else {
                result+=paramsBuf.get(i);
            }
        }
        return result;
    }

    /**
     * 返回key的值
     * @param map
     * @param key
     * @return
     */
    private static String getParamString(Map map, String key) {
        String buf = "";
        if (map.get(key) instanceof String[]) {
            buf = ((String[]) map.get(key))[0];
        } else {
            buf = (String) map.get(key);
        }
        return buf;
    }

    /**
     * @description 将xml字符串转换成map
     * @param xml
     * @return Map
     */
    public static Map<String, String> readStringXmlOut(String xml) {
        if(StringUtils.isEmpty(xml)) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(xml); // 将字符串转为XML
            Element rootElt = doc.getRootElement(); // 获取根节点
            @SuppressWarnings("unchecked")
            List<Element> list = rootElt.elements();// 获取根节点下所有节点
            for (Element element : list) { // 遍历节点
                map.put(element.getName(), element.getText()); // 节点的name为map的key，text为map的value
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * Map转Xml
     * @param arr
     * @return
     */
    public static String mapToXml(Map<String, String> arr) {
        StringBuffer xml = new StringBuffer();
        xml.append("<xml>");
        Iterator<Map.Entry<String, String>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = iter.next();
            String k = entry.getKey();
            String v = entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)
                    ||"sign".equalsIgnoreCase(k) || "notify_url".equalsIgnoreCase(k)
                    ||"ToUserName".equals(k) || "FromUserName".equals(k)
                    ||"MsgType".equals(k)) {
                xml.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
            }else {
                xml.append("<"+k+">"+v+"</"+k+">");
            }
        }
        xml.append("</xml>");
        return xml.toString();
    }

    public static void main(String[] args) {
        String s = "<?xml version=\"1.0\" encoding=\"utf-8\"?><BasePart>"
                + "<OrderStatus>1</OrderStatus>"
                + "<PayNo>2017002243411189</PayNo>"
                + "<OrderId>1000000007455202</OrderId>"
                + "<OrderAmt>4549.72</OrderAmt>"
                + "<PlatformCode>47</PlatformCode>"
                + "<PlatformName>分销支付宝移动支付</PlatformName>"
                + "<PayDiscount>0</PayDiscount>"
                + "<AliPayLink><![CDATA[_input_charset=UTF-8&body=安盛天平订单&extern_token=&it_b_pay=1c&notify_url=http://pay.95550.cn:30880/wspayment/aliPayResult.do&out_trade_no=1000000007455202&partner=2088121402823023&payment_type=1&seller_id=2088121402823023&service=mobile.securitypay.pay&sign=Xs5F66oNcLfhaNCQOcTRZtB%2FEQsy4wC11KGbA%2Br8O5hJ2aEZIhb2D9zQzrC1mxYLbbKCJhNetlpKdfiovqAJL%2BSvBAyCihrxh2%2FaEDDJRkePTkyQVjPYTtt1WVG8CMqzjF4MnrvVYpyeaNal46IgU5KXQFRTPKbtg5wfmWgS%2FKk%3D&sign_type=RSA&subject=安盛天平订单&total_fee=4549.72]]></AliPayLink></BasePart>";
        Map<String, String> map = new HashMap<String, String>();
        map =  readStringXmlOut(s);

        for(Object m: map.keySet()){

            if(m.toString().equals("AliPayLink")){
               String [] ss =  map.get(m).toString().split("&");
                for (String sf:ss
                     ) {
                    System.out.println(sf);
                }

            }
        }
    }
}
